package com.the.ui.widge;//  ┏┓　　　┏┓
//┏┛┻━━━┛┻┓
//┃　　　　　　　┃
//┃　　　━　　　┃
//┃　┳┛　┗┳　┃
//┃　　　　　　　┃
//┃　　　┻　　　┃
//┃　　　　　　　┃
//┗━┓　　　┏━┛
//    ┃　　　┃                  神兽保佑
//    ┃　　　┃                  永无BUG！
//    ┃　　　┗━━━┓
//    ┃　　　　　　　┣┓
//    ┃　　　　　　　┏┛
//    ┗┓┓┏━┳┓┏┛
//      ┃┫┫　┃┫┫
//      ┗┻┛　┗┻┛

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import java.util.ArrayList;
import java.util.List;

/**
 * @author The one
 * @date 2021-11-05 15:52
 * @describe 流式布局
 * @email 625805189@qq.com
 * @remark
 */
public class FlowLayout extends ViewGroup {

    /**
     * 每一行的子View
     */
    private List<View> mLineViews;
    /**
     * 所有的行 一行一行的存储
     */
    private List<List<View>> mViews;
    /**
     * 每一行的高度
     */
    private List<Integer> mHeights;

    public FlowLayout(Context context) {
        super(context, null);
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
    }

    public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init(){
        mLineViews = new ArrayList<>();
        mViews = new ArrayList<>();
        mHeights = new ArrayList<>();
    }

    /**
     * 创建子View的LayoutParams;测量时需计算子View的margin
     */
    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(),attrs);
    }

    /**
     * 测量 -  先测量子View,再根据子View的尺寸，计算自己的
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // 获取限制的值
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        // 记录当前行的宽度和高度
        // 宽度是当前行子view的宽度之和
        int lineWidth = 0;
        // 高度是当前行所有子View中高度的最大值
        int lineHeight = 0;

        // 整个流式布局的宽度和高度
        // 所有行中宽度的最大值
        int flowLayoutWidth = 0;
        // 所有行的高度的累加
        int flowLayoutHeight = 0;

        init();

        // 获取padding
        int paddingHorizontal = getPaddingLeft() +getPaddingRight();
        int paddingVertical = getPaddingTop() + getPaddingBottom();

        // 所有孩子的个数
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            // 测量子孩子
//            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            measureChildWithMargins(child,widthMeasureSpec,0,heightMeasureSpec,0);
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            int childMarginHorizontal = lp.leftMargin + lp.rightMargin;
            int childMarginVertical = lp.topMargin + lp.bottomMargin;
            // 测量后拿到子孩子的宽高
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            // 是否换行: 已经放入的宽度总和+即将放入child宽度 是否 大于 总宽度
            if (lineWidth + childWidth + childMarginHorizontal > widthSize- paddingHorizontal) {
                mViews.add(mLineViews);
                // 创建新的一行
                mLineViews = new ArrayList<>();
                // 比较每行的宽，取最大的一个
                flowLayoutWidth = Math.max(flowLayoutWidth, lineWidth);
                // 累加高度
                flowLayoutHeight += lineHeight;
                mHeights.add(lineHeight);
                // 清零每行的宽高记录
                lineWidth = 0;
                lineHeight = 0;
            }

            // 把子View放入到一行的数据集
            mLineViews.add(child);

            // 累加一行的宽度
            lineWidth += childWidth + childMarginHorizontal;
            // 比较得到一行中所有的子View,取最高的最为一行的高度
            lineHeight = Math.max(lineHeight, childHeight + childMarginVertical);

            if(i == childCount - 1){
                flowLayoutWidth = Math.max(flowLayoutWidth,lineWidth);
                flowLayoutHeight += lineHeight;
                mViews.add(mLineViews);
                mHeights.add(lineHeight);
            }

        }

        flowLayoutHeight += paddingVertical;

        // 保存尺寸
        setMeasuredDimension(
                // 如果是 EXACTLY 直接就是 widthSize ，否则就取计算得来的 flowLayoutWidth
                widthMode == MeasureSpec.EXACTLY ? widthSize : flowLayoutWidth,
                // 同上
                heightMode == MeasureSpec.EXACTLY? heightSize:flowLayoutHeight );

    }

    /**
     * 布局 - 摆放子View位置
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // 起始的X，Y
        int currX = getPaddingLeft();
        int currY = getPaddingTop();
        for (int i = 0; i < mViews.size(); i++) {
            // 拿到一行的子View
            List<View> lineViews = mViews.get(i);
            // 拿到一行的高度
            int lineHeight = mHeights.get(i);

            // 处理每行中的View
            for (int j = 0; j < lineViews.size(); j++) {
                View child = lineViews.get(j);
                MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
                // 子View的左上右下坐标
                int left = currX + lp.leftMargin;
                int top = currY + lp.topMargin;
                int right = left + child.getMeasuredWidth();
                int bottom = top + child.getMeasuredHeight();
                // 摆放子View
                child.layout(left,top,right,bottom);
                // 一行摆放好一个View后，累加宽度，作为一行下一个View的起始X坐标
                // 当前View的右边位置+右边的margin=下一个View开始的位置
                currX = right + lp.rightMargin;
            }
            // 摆放好一行后
            // 累加高度，作为下一行的起始Y坐标
            currY += lineHeight;
            // 清零X起始坐标
            currX = getPaddingLeft();
        }
    }


}
